home *** CD-ROM | disk | FTP | other *** search
/ Aminet 6 / Aminet 6 - June 1995.iso / Aminet / gfx / 3d / irit50src.lha / irit5 / prsr_lib / soc_clnt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-19  |  21.4 KB  |  605 lines

  1. /*****************************************************************************
  2. *   Sockets routines to handle socket io of objects.                 *
  3. *                                         *
  4. * Written by:  Gershon Elber                Ver 0.1, June 1993.  *
  5. *****************************************************************************/
  6.  
  7. #include <stdio.h>
  8. #include <sys/types.h>
  9.  
  10. #ifdef __UNIX__
  11. #if (defined(ultrix) && defined(mips)) || defined(_AIX) || defined(sgi)
  12. #    include <fcntl.h>
  13. #else
  14. #    include <sys/fcntl.h>
  15. #endif /* (ultrix && mips) || _AIX || sgi */
  16. #include <sys/socket.h>
  17. #if defined(__hpux) || defined(sun)
  18. #    include <sys/file.h>
  19. #endif /* __hpux || sun */
  20. #include <netinet/in.h>
  21. #include <netdb.h>
  22. #include <errno.h>
  23. #endif /* __UNIX__ */
  24.  
  25. #ifdef OS2GCC
  26. #    include <os2.h>
  27. #endif /* OS2GCC */
  28.  
  29. #ifdef __WINNT__
  30. #include <stdlib.h>
  31. #include <windows.h>
  32. #include <winsock.h>
  33. #include <io.h>
  34. #endif /* __WINNT__ */
  35.  
  36. #ifdef AMIGA
  37. #include <string.h>
  38. #include <exec/types.h>
  39. #include <exec/ports.h>
  40. #include <exec/memory.h>
  41. #include <proto/dos.h>
  42. #include <proto/exec.h>
  43. #endif /* AMIGA */
  44.  
  45. #include "irit_sm.h"
  46. #include "prsr_loc.h"
  47. #include "irit_soc.h"
  48.  
  49. /* #define DEBUG_ECHO */
  50.  
  51. static void SocketPrintError(char *Str);
  52. static void SocUnReadChar(int Handler, char c);
  53. static int SocReadObjPrefix(int Handler);
  54.  
  55. /*****************************************************************************
  56. * DESCRIPTION:                                                               *
  57. * IO error print routine.                             *
  58. *                                                                            *
  59. * PARAMETERS:                                                                *
  60. *   Str:      To output to stderr as a message.                              *
  61. *                                                                            *
  62. * RETURN VALUE:                                                              *
  63. *   void                                                                     *
  64. *****************************************************************************/
  65. static void SocketPrintError(char *Str)
  66. {
  67. #   if defined(__UNIX__) || defined(OS2GCC) || defined(AMIGA)
  68.     perror(Str);
  69. #   endif /* __UNIX__ || OS2GCC */
  70. #   ifdef __WINNT__
  71.     fprintf(stderr, "iritserver: %s error %d\n", Str, WSAGetLastError());
  72. #   endif /* __WINNT__ */
  73. }
  74.  
  75. /*****************************************************************************
  76. * DESCRIPTION:                                                               M
  77. *  Sets echo printing of read input.                                         M
  78. *                                                                            *
  79. * PARAMETERS:                                                                M
  80. *   Handler: The socket info handler index.                                  M
  81. *   EchoInput:   TRUE to echo every character read in.                       M
  82. *                                                                            *
  83. * RETURN VALUE:                                                              M
  84. *   void                                                                     M
  85. *                                                                            *
  86. * KEYWORDS:                                                                  M
  87. *   SocEchoInput, ipc                                                        M
  88. *****************************************************************************/
  89. void SocEchoInput(int Handler, int EchoInput)
  90. {
  91.     _IPStream[Handler].EchoInput = EchoInput;
  92. }
  93.  
  94. /*****************************************************************************
  95. * DESCRIPTION:                                                               M
  96. * Non blocking read of a single character.                     M
  97. *   Returns EOF if no data is found.                         M
  98. *                                                                            *
  99. * PARAMETERS:                                                                M
  100. *   Handler: The socket info handler index.                                  M
  101. *                                                                            *
  102. * RETURN VALUE:                                                              M
  103. *   int:        Read character or EOF if none found.                         M
  104. *                                                                            *
  105. * KEYWORDS:                                                                  M
  106. *   SocReadCharNonBlock, ipc                                                 M
  107. *****************************************************************************/
  108. int SocReadCharNonBlock(int Handler)
  109. {
  110.     int c;
  111. #ifdef AMIGA
  112.     struct IritMessage *msg;
  113. #endif /* AMIGA */
  114.  
  115.     if (_IPStream[Handler].UnGetChar >= 0) {
  116.     c = _IPStream[Handler].UnGetChar;
  117.     _IPStream[Handler].UnGetChar = -1;
  118.     return c;
  119.     }
  120.     else if (_IPStream[Handler].BufferPtr < _IPStream[Handler].BufferSize) {
  121.     c = _IPStream[Handler].Buffer[_IPStream[Handler].BufferPtr++];
  122.     return c;
  123.     }
  124.  
  125. #ifdef OS2GCC
  126.     DosRead(_IPStream[Handler].pipIrit, _IPStream[Handler].Buffer,
  127.         LINE_LEN_LONG, (PULONG) &_IPStream[Handler].BufferSize);
  128. #endif /* OS2GCC */
  129. #if defined(__UNIX__) || defined(__WINNT__)
  130.     _IPStream[Handler].BufferSize = recv(_IPStream[Handler].CommuSoc,
  131.                      _IPStream[Handler].Buffer,
  132.                      LINE_LEN_LONG, 0);
  133. #endif /* __UNIX__ || __WINNT__ */
  134. #ifdef AMIGA
  135.     msg = (struct IritMessage *)GetMsg(_IPStream[Handler].CommuSoc);
  136.     if (msg) {
  137.         _IPStream[Handler].BufferSize = msg->nbytes;
  138.     memcpy(_IPStream[Handler].Buffer, msg->txt, msg->nbytes);
  139.     ReplyMsg((struct Message *)msg);
  140.     }else{
  141.         _IPStream[Handler].BufferSize = 0;
  142.     }
  143. #endif /* AMIGA */
  144.  
  145.     if (_IPStream[Handler].BufferSize > 0) {
  146.     if (_IPStream[Handler].EchoInput) {
  147.         int i;
  148.         unsigned char
  149.         *p = _IPStream[Handler].Buffer;
  150.  
  151.         if (_IPStream[Handler].IsBinary) {
  152.         for (i = 0; i < _IPStream[Handler].BufferSize; i++) {
  153.             if (i % 16 == 0)
  154.             printf("\n%04x: ", i);
  155.             printf("%02x ", *p++);
  156.         }
  157.         printf("\n");
  158.         }
  159.         else
  160.         for (i = 0; i < _IPStream[Handler].BufferSize; i++)
  161. #if 0    /* if putc is macro, weirdness will occur */
  162.             putc(*p++, stdout);
  163. #else
  164.         {
  165.             unsigned char tmp = *p++;
  166.             putc(tmp, stdout);
  167.         }
  168. #endif
  169.     }
  170.     _IPStream[Handler].BufferPtr = 0;
  171.     c = _IPStream[Handler].Buffer[_IPStream[Handler].BufferPtr++];
  172.     }
  173.     else
  174.     c = EOF;
  175.  
  176.     return c;
  177. }
  178.  
  179. /*****************************************************************************
  180. * DESCRIPTION:                                                               *
  181. * Unget one chararacter read from client port.                               *
  182. *                                                                            *
  183. * PARAMETERS:                                                                *
  184. *   Handler:  The socket info handler index.                                 *
  185. *   c:        Character to unget.                                            *
  186. *                                                                            *
  187. * RETURN VALUE:                                                              *
  188. *   void                                                                     *
  189. *                                                                            *
  190. * KEYWORDS:                                                                  *
  191. *   SocUnReadChar, ipc                                                       *
  192. *****************************************************************************/
  193. static void SocUnReadChar(int Handler, char c)
  194. {
  195.     _IPStream[Handler].UnGetChar = c;
  196. }
  197.  
  198. /*****************************************************************************
  199. * DESCRIPTION:                                                               *
  200. * Gets a single line for syncronization purposes that will prefix an object. *
  201. *   Returns TRUE if prefix found, FALSE otherwise.                           *
  202. *                                                                            *
  203. * PARAMETERS:                                                                *
  204. *   Handler: The socket info handler index.                                  *
  205. *                                                                            *
  206. * RETURN VALUE:                                                              *
  207. *   int:        TRUE if prefic of object was found, FALSE otherwise          *
  208. *****************************************************************************/
  209. static int SocReadObjPrefix(int Handler)
  210. {
  211.     if (_IPStream[Handler].IsBinary) {
  212.     int c;
  213.  
  214.     if ((c = SocReadCharNonBlock(Handler)) != EOF) {
  215.         SocUnReadChar(Handler, (char) c);
  216.         return TRUE;
  217.     }
  218.     }
  219.     else {
  220.     if (SocReadCharNonBlock(Handler) == '[') {
  221.         SocUnReadChar(Handler, '[');
  222.         return TRUE;
  223.     }
  224.     }
  225.  
  226.     return FALSE;
  227. }
  228.  
  229. /*****************************************************************************
  230. * DESCRIPTION:                                                               M
  231. * Non blocking read of a single line. Returns NULL if no line is available.  M
  232. *                                                                            *
  233. * PARAMETERS:                                                                M
  234. *   Handler: The socket info handler index.                                  M
  235. *                                                                            *
  236. * RETURN VALUE:                                                              M
  237. *   char *:     Read line, or NULL if unavailable.                           M
  238. *                                                                            *
  239. * KEYWORDS:                                                                  M
  240. *   SocReadLineNonBlock, ipc                                                 M
  241. *****************************************************************************/
  242. char *SocReadLineNonBlock(int Handler)
  243. {
  244.     static char Line[LINE_LEN_LONG];
  245.     static int
  246.     LineLen = 0;
  247.  
  248.     while (TRUE) {
  249.     int c;
  250.  
  251.     if ((c = SocReadCharNonBlock(Handler)) != EOF) {
  252.         if (c == '\n' || c == '\r') {
  253.         Line[LineLen++] = c;
  254.         Line[LineLen] = 0;
  255.  
  256.         LineLen = 0;
  257.         return Line;
  258.         }
  259.         else if (LineLen >= LINE_LEN_LONG - 1) {
  260.         IritPrsrFatalError("Socket read line too long\n");
  261.         exit(1);
  262.         }
  263.         else {
  264.         Line[LineLen++] = c;
  265.         }
  266.     }
  267.     else
  268.         return NULL;
  269.     }
  270. }
  271.  
  272. /*****************************************************************************
  273. * DESCRIPTION:                                                               M
  274. *  Opens the client's socket. Returns handler if succesful.                  M
  275. *                                                                            *
  276. * PARAMETERS:                                                                M
  277. *   BinaryIPC:     Do we want to communicate text or binary?                   M
  278. *   Read:     Is this socket for read (TRUE) or write (FALSE).            M
  279. *                                                                            *
  280. * RETURN VALUE:                                                              M
  281. *   int:         Non negative handler if successful, -1 otherwise.           M
  282. *                                                                            *
  283. * KEYWORDS:                                                                  M
  284. *   SocClientCreateSocket, ipc                                               M
  285. *****************************************************************************/
  286. int SocClientCreateSocket(int BinaryIPC, int Read)
  287. {
  288.     int Handler;
  289. #ifdef AMIGA
  290.     int len;
  291.     char *name, buf[4];
  292.     static int timescalled = 0;
  293. #endif /* AMIGA */
  294. #if defined(__UNIX__) || defined(__WINNT__)
  295.     int s;
  296.     char *HostName, *PortNum, HostNameStr[LINE_LEN];
  297.     struct sockaddr_in Sain;
  298.     struct hostent *Host;
  299. #endif /* __UNIX__ || __WINNT__ */
  300. #ifdef OS2GCC
  301.     char *Port;
  302.     ULONG rc,
  303.     ulActionTaken, ulFileSize, ulFileAttribute, ulOpenFlag, ulOpenMode;
  304. #endif /* OS2GCC */
  305.  
  306.     /* Allocate handler. */
  307.     Handler = IritPrsrOpenStreamFromSocket(0, TRUE, BinaryIPC);
  308.  
  309. #if defined(__UNIX__) || defined(__WINNT__)
  310. #ifdef __WINNT__
  311.     {
  312.     WSADATA WSAData;
  313.  
  314.     if ((s = WSAStartup(MAKEWORD(1, 1), &WSAData)) != 0 ||
  315.         LOBYTE(WSAData.wVersion) != 1 ||
  316.         HIBYTE(WSAData.wVersion) != 1) {
  317.         fprintf(stderr, "iritserver: WSAStartup: error %d\n",
  318.             WSAGetLastError());
  319.         exit(1);
  320.     }
  321.     }
  322. #endif
  323.  
  324.     /* Get port address. */
  325.     gethostname(HostNameStr, LINE_LEN);
  326.     if ((HostName = getenv("IRIT_SERVER_HOST")) == NULL)
  327.     HostName = HostNameStr;
  328.  
  329.     if ((Host = gethostbyname(HostName)) == NULL) {
  330.     SocketPrintError("iritclient: hostname unknown\n");
  331.     return -1;
  332.     }
  333.  
  334.     ZAP_MEM(&Sain, sizeof(struct sockaddr_in));
  335.     GEN_COPY(&Sain.sin_addr, Host -> h_addr_list[0], Host -> h_length);
  336.     Sain.sin_family = AF_INET;
  337.  
  338.     if ((PortNum = getenv("IRIT_SERVER_PORT")) != NULL)
  339.     Sain.sin_port = atoi(PortNum);
  340.     else {
  341.     SocketPrintError("iritclient: hostport unknown (set IRIT_SERVER_PORT)\n");
  342.     return -1;
  343.     }
  344.  
  345.     /* Create the socket, make it nonblocking if Read and connect. */
  346.     if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  347.     SocketPrintError("iritclient: socket");
  348.     return -1;
  349.     }
  350.  
  351.     if (Read) {
  352. #ifdef __UNIX__
  353. #ifdef __hpux
  354.         if (fcntl(s, F_SETFL, O_NDELAY) < 0) {
  355. #else
  356.         if (fcntl(s, F_SETFL, FNDELAY) < 0) {
  357. #endif /* __hpux */
  358.         SocketPrintError("iritclient: fcntl");
  359.         return -1;
  360.         }
  361. #endif /* __UNIX__ */
  362.     }
  363.  
  364.     while (connect(s, (struct sockaddr *) &Sain,
  365.            sizeof(struct sockaddr_in)) < 0) {
  366. #    ifdef __UNIX__
  367.         if (errno == EINPROGRESS)
  368.         break;
  369. #    endif /* __UNIX__ */
  370. #    ifdef __WINNT__
  371.         if (WSAGetLastError() == WSAEINPROGRESS)
  372.         break;
  373. #    endif /* __WINNT__ */
  374.     SocketPrintError("iritclient: connect");
  375.     return -1;
  376.     }
  377.  
  378.     _IPStream[Handler].CommuSoc = s;
  379. #endif /* __UNIX__ || __WINNT__ */
  380.  
  381. #ifdef OS2GCC
  382.     if ((Port = getenv("IRIT_SERVER_PORT")) == NULL) {
  383.     fprintf(stderr, "No IRIT_SERVER_PORT environment variable, \"\\pipe\\irit_1\" assumed.\n");
  384.     Port = "\\pipe\\irit_1";
  385.     }
  386.  
  387.     DosWaitNPipe(Port, NP_WAIT);
  388.     ulFileSize = 0;
  389.     ulFileAttribute = 0;
  390.     ulOpenFlag = OPEN_ACTION_OPEN_IF_EXISTS;
  391.     ulOpenMode = OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE;
  392.  
  393.     rc = DosOpen(Port,
  394.          &_IPStream[Handler].pipIrit,
  395.          &ulActionTaken,
  396.          ulFileSize,
  397.          ulFileAttribute,
  398.          ulOpenFlag,
  399.          ulOpenMode,
  400.          NULL);
  401.  
  402.     if (rc != 0) {
  403.         DosBeep(1000, 100);
  404.         exit(1);
  405.     }
  406.  
  407.     _IPStream[Handler].CommuSoc = 1;
  408. #endif /* OS2GCC */
  409.  
  410. #ifdef AMIGA
  411.     timescalled++;
  412.     if (timescalled % 2) {
  413.     len = GetVar(SERVER_VAR, buf, sizeof(buf), GVF_GLOBAL_ONLY);
  414.     if (len < 0) {
  415.         SocketPrintError
  416.         ("iritclient: cannot get synchronization environment variable");
  417.         return -1;
  418.     }
  419.     DeleteVar(SERVER_VAR, GVF_GLOBAL_ONLY);
  420.     }
  421.  
  422.     name = getenv("IRIT_SERVER_PORT");
  423.     if (!name) {
  424.     SocketPrintError("iritclient: hostport unknown (set IRIT_SERVER_PORT)\n");
  425.     return -1;
  426.     }
  427.     Forbid();
  428.     _IPStream[Handler].CommuSoc = FindPort(name);
  429.     Permit();
  430.     if (!_IPStream[Handler].CommuSoc) {
  431.     SocketPrintError("iritclient: FindPort");
  432.     return -1;
  433.     }
  434.  
  435.     _IPStream[Handler].IsBinary = BinaryIPC;
  436.     buf[0] = '\0';
  437.     if (timescalled % 2) {
  438.     SetVar(CLIENT_VAR, buf, -1, GVF_GLOBAL_ONLY);
  439.     /* This beast busy-waits! Reduce its priority so that we don't hog
  440.        other tasks, namely irit. */
  441.     }
  442.     _IPStream[Handler].oldpri = SetTaskPri(FindTask(0L), -1);
  443. #endif /* AMIGA */
  444.  
  445.     _IPStream[Handler].IsBinary = BinaryIPC;
  446.  
  447.     return Handler;
  448. }
  449.  
  450. /*****************************************************************************
  451. * DESCRIPTION:                                                               M
  452. *  Close the client's socket.                                                M
  453. *                                                                            *
  454. * PARAMETERS:                                                                M
  455. *   Handler: The socket info handler index.                                  *
  456. *                                                                            *
  457. * RETURN VALUE:                                                              M
  458. *   void                                                                     M
  459. *                                                                            *
  460. * KEYWORDS:                                                                  M
  461. *   SocClientCloseSocket, ipc                                                M
  462. *****************************************************************************/
  463. void SocClientCloseSocket(int Handler)
  464. {
  465. #ifndef AMIGA
  466.     if (_IPStream[Handler].CommuSoc > 0) {
  467. #else
  468.     if (_IPStream[Handler].CommuSoc != 0) {
  469. #endif
  470. #ifdef __UNIX__
  471.     if (close(_IPStream[Handler].CommuSoc) != 0)
  472.         SocketPrintError("iritclient: close");
  473. #endif /* __UNIX__ */
  474. #ifdef __WINNT__
  475.     closesocket(_IPStream[Handler].CommuSoc);
  476. #endif /* __WINNT__ */
  477. #ifdef OS2GCC
  478.     DosClose(_IPStream[Handler].pipIrit);
  479. #endif /* OS2GCC */
  480. #ifdef AMIGA
  481.     SetTaskPri(FindTask(0L), _IPStream[Handler].oldpri);
  482. #endif /* AMIGA */
  483.  
  484.     _IPStream[Handler].CommuSoc = 0;
  485.     }
  486. }
  487.  
  488. /*****************************************************************************
  489. * DESCRIPTION:                                                               M
  490. * Attempts to read (non blocking) an object from socket.             M
  491. * If read is successful the object is returned, otherwise NULL is returned.  M
  492. *                                                                            *
  493. * PARAMETERS:                                                                M
  494. *   Handler: The socket info handler index.                                  *
  495. *                                                                            *
  496. * RETURN VALUE:                                                              M
  497. *   IPObjectStruct *:  An object if read one, NULL otherwise.                M
  498. *                                                                            *
  499. * KEYWORDS:                                                                  M
  500. *   SocReadOneObject, ipc                                                    M
  501. *****************************************************************************/
  502. IPObjectStruct *SocReadOneObject(int Handler)
  503. {
  504.     char *ErrorMsg;
  505.     IPObjectStruct *PObj;
  506.  
  507. #ifndef AMIGA
  508.     if (_IPStream[Handler].CommuSoc > 0 && SocReadObjPrefix(Handler)) {
  509. #else
  510.     if (_IPStream[Handler].CommuSoc != 0 && SocReadObjPrefix(Handler)) {
  511. #endif
  512.     IritPrsrSetReadOneObject(TRUE);
  513.  
  514.     if (_IPStream[Handler].IsBinary) {
  515.         PObj = IritPrsrGetBinObject(Handler);
  516.     }
  517.     else {
  518.         PObj = IritPrsrGetObjects(Handler);
  519.     }
  520.     }
  521.     else
  522.     PObj = NULL;
  523.  
  524.     if (IritPrsrParseError(_IPStream[Handler].LineNum, &ErrorMsg)) {
  525.     fprintf(stderr, "Socket: %s\n", ErrorMsg);
  526.     }
  527.  
  528.     return PObj;
  529. }
  530.  
  531. /*****************************************************************************
  532. * DESCRIPTION:                                                               M
  533. *   Accept a connection. Must be called by clients at the beginning.         M
  534. *                                                                            *
  535. * PARAMETERS:                                                                M
  536. *   PrgmInput:  A handler to the Program's input channel.             M
  537. *   PrgmOutput: A handler to the Program's output channel.             M
  538. *                                                                            *
  539. * RETURN VALUE:                                                              M
  540. *   int:        TRUE, if succesful, FALSE otherwise.                         M
  541. *                                                                            *
  542. * KEYWORDS:                                                                  M
  543. *   IritPrsrClntAcceptConnect                                                M
  544. *****************************************************************************/
  545. int IritPrsrClntAcceptConnect(int *PrgmInput, int *PrgmOutput)
  546. {
  547.     static char Line[LINE_LEN];
  548.     int i, Input, Output,
  549.     IsBinary = getenv("IRIT_BIN_IPC") != NULL;
  550.     IPObjectStruct
  551.     *PObj = NULL;
  552.  
  553.     if ((Input = SocClientCreateSocket(IsBinary, TRUE)) >= 0) {
  554.     for (i = 0; i < SOC_TIME_OUT; i++) {
  555.         if ((PObj = SocReadOneObject(Input)) != NULL) {
  556.         if (!IP_IS_STR_OBJ(PObj) ||
  557.             strncmp(PObj -> U.Str, "IRIT_SERVER_PORT=", 17) != 0) {
  558.             IPFreeObject(PObj);
  559.             return FALSE;
  560.         }
  561.         strcpy(Line, PObj -> U.Str);
  562.         IPFreeObject(PObj);
  563.         break;
  564.         }
  565.         IritSleep(10);
  566.     }
  567.     if (i >= SOC_TIME_OUT)
  568.         return FALSE;
  569.     }
  570.     else
  571.     return FALSE;
  572.  
  573.     putenv(Line);
  574.  
  575.     if ((Output = SocClientCreateSocket(IsBinary, FALSE)) < 0)
  576.     return FALSE;
  577.  
  578.     *PrgmInput = Input;
  579.     *PrgmOutput = Output;
  580.  
  581.     return TRUE;
  582. }
  583.  
  584. /*****************************************************************************
  585. * DESCRIPTION:                                                               M
  586. *   Close a connection. Must be called by clients at the end.                M
  587. *                                                                            *
  588. * PARAMETERS:                                                                M
  589. *   PrgmInput:  A handler to the Program's input channel.             M
  590. *   PrgmOutput: A handler to the Program's output channel.             M
  591. *                                                                            *
  592. * RETURN VALUE:                                                              M
  593. *   int:        TRUE, if succesful, FALSE otherwise.                         M
  594. *                                                                            *
  595. * KEYWORDS:                                                                  M
  596. *   IritPrsrClntCloseConnect                                                 M
  597. *****************************************************************************/
  598. int IritPrsrClntCloseConnect(int PrgmInput, int PrgmOutput)
  599. {
  600.     SocClientCloseSocket(PrgmInput);
  601.     SocClientCloseSocket(PrgmOutput);
  602.  
  603.     return TRUE;
  604. }
  605.